package cn.crism.chatme.netty;


import cn.crism.chatme.SpringUtil;
import cn.crism.chatme.enums.MsgActionEnum;
import cn.crism.chatme.service.ChatMsgService;
import cn.crism.chatme.utils.JsonUtils;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 
 * @author leifengyue
 * @desc TextWebSocketFrame 专门用来处理文本的对象  Frame 是载体
 */
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
	
	// 用于管理和记录所有客户端的Channel
	private static ChannelGroup users = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		cause.printStackTrace();
		// 关闭连接 移除Channel
		ctx.channel().close();
		users.remove(ctx.channel());
	}

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {

		Channel currentChannel = ctx.channel();
		// 1.客户端发送过来的文本消息
		String content = msg.text();
		DataContent dataContent = JsonUtils.jsonToPojo(content,DataContent.class);

		// 2 判断消息类型 处理不同的业务
		Integer action = dataContent.getAction();
		// 2.1 当websocket第一次open的时候 初始化channel 把channel和用户id关联
		if (action == MsgActionEnum.CONNECT.type){
			String sendUserId = dataContent.getChatMsg().getSenderId();
			UserChannelRel.put(sendUserId,currentChannel);
//
//			for (Channel c:users){
//				System.out.println(c.id().asLongText());
//			}
			UserChannelRel.output();

		}// 2.2 聊天类型的消息，把聊天记录保存到数据库,标记消息状态未签收
		else if (action == MsgActionEnum.CHAT.type){
			ChatMsg chatMsg = dataContent.getChatMsg();
//			String msgText = chatMsg.getMsg();
//			String senderId = chatMsg.getSenderId();
			String receiverId = chatMsg.getReceiverId();


			ChatMsgService chatMsgService = (ChatMsgService)SpringUtil.getBean("chatMsgServiceImpl");
			String msgId = chatMsgService.saveMsg(chatMsg);
			chatMsg.setMsgId(msgId);

			DataContent dataContentMsg = new DataContent();
			dataContentMsg.setChatMsg(chatMsg);

			// 发送消息
			// 从全局channel获取接收方的channel
			Channel  receiverChannel = UserChannelRel.get(receiverId);
			if (receiverChannel == null){
				// 用户不在线，离线推送消息。TODO

			} else {
				// 当receiverChannel不为空的时候，从ChannelGroup去查找对应的channel是否存在
				Channel findChannel = users.find(receiverChannel.id());
				if (findChannel != null) {
					// 用户在线
					receiverChannel.writeAndFlush(new TextWebSocketFrame(JsonUtils.objectToJson(dataContentMsg)));
				} else {
					// 用户离线 TODO 推送消息
				}
			}

		}// 2.3 签收消息 标记消息状态为签收
		else if (action == MsgActionEnum.SIGNED.type){
			ChatMsgService chatMsgService = (ChatMsgService)SpringUtil.getBean("chatMsgServiceImpl");
			String msgId = dataContent.getExtand();
			String msgIds[] = msgId.split(",");
			List<String> msgIdList = new ArrayList<>();
			for (String mid: msgIds){
				if (StringUtils.isNotBlank(mid)){
					msgIdList.add(mid);
				}
			}
//			System.out.println(msgIdList.toString());
			if (msgIdList!=null && !msgIdList.isEmpty() && msgIdList.size()>0){
				// 批量签收
				chatMsgService.updateMsgSigned(msgIdList);
			}
		}// 2.4 心跳类型的消息
		else if (action == MsgActionEnum.KEEPALIVE.type){
			System.out.println("收到channel["+ currentChannel +"]心跳包!");
		}

	}

	// 获取客户端channel 放入ChannelGroup 进行管理
	@Override
	public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
		users.add(ctx.channel());
	}

	@Override
	public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
		// handlerRemoved 触发后 ChannelGroup会自动移除客户端channel
		users.remove(ctx.channel());
		System.out.println("LongID: "+ctx.channel().id().asLongText());
		System.out.println("ShortID: "+ctx.channel().id().asShortText());
	}
	
	
}
